#pragma once
#include <windows.h>
#include <map>
#include <vector>
#include <string>


#include "Win32/Window.h"



using namespace std;
#include "Interfaces/ITexture.h"
#include "Interfaces/IVertexBuffer.h"
#include "Interfaces/IIndexBuffer.h"
#include "Interfaces/IVertexDeclaration.h"
#include "Interfaces/IShader.h"
#include "Interfaces/IRendererContext.h"
#include "Camera.h"
#include "Math.h"
using namespace gname;
namespace gengine
{
	namespace kernel
	{


    enum VboAccses
	{
		VBOACCESS_READ_ONLY				=	0x88B8,
	    VBOACCESS_WRITE_ONLY		    =	0x88B9,
	    VBOACCESS_READ_WRITE			=	0x88BA
	};

	enum VboUsage
	{
		VBOUSAGE_STREAM_DRAW			=  0x88E0,
		VBOUSAGE_STREAM_READ			=  0x88E1,
		VBOUSAGE_STREAM_COPY			=  0x88E2,
		VBOUSAGE_STATIC_DRAW			=  0x88E4,
		VBOUSAGE_STATIC_READ			=  0x88E5,
		VBOUSAGE_STATIC_COPY			=  0x88E6,
		VBOUSAGE_DYNAMIC_DRAW			=  0x88E8,
		VBOUSAGE_DYNAMIC_READ			=  0x88E9,
		VBOUSAGE_DYNAMIC_COPY			=  0x88EA
	};
	
	

	/* This abastract class can be implemented with arbitrary GAPI
	*/

	class IGraphicsDevice
	{
	public:
		/* This structure need
		*  to create low level graphics device
		*/
		enum DevType
		{
			OpenGL,
			Direct3D
		};

		struct ClearType
		{
			bool ZBuffer       ;
			bool StencilBuffer ;
			bool Color         ;
		};
class DeviceParameters
{
public:
	DeviceParameters ( int w=640, int h=480, int bits=24, int f=75, int depthBits=24, bool fullscreen = false ,int glMinorV = 2,int glMadjorV = 1)
	{
		bpp     = bits;
		width   = w;
		height  = h;
		freq    = f;
		glMinorVersion  =  glMinorV;
		glMadjorVersion =  glMadjorV;
		depth_bpp = depthBits;
		isFullscreen = fullscreen;
		
	}

	DeviceParameters & operator =( const DeviceParameters & mode )
	{
		bpp     = mode.getBitsPerPixel();
		width   = mode.getWidth();
		height  = mode.getHeight();
		freq    = mode.getFreq();
		depth_bpp = mode.getDepthBitsPerPixel();
		isFullscreen = mode.isFullscreen;
		

		return *this;
	}

	bool operator == ( const DeviceParameters & mode) const
	{
		return (width == mode.width) &&(height == mode.height) && (bpp == mode.bpp) ;
			
	}

	int	getBitsPerPixel () const
	{
		return bpp;
	}

	int	getDepthBitsPerPixel () const
	{
		return depth_bpp;
	}

	int	getWidth () const
	{
		return width;
	}

	int	getHeight () const
	{
		return height;
	}

	int	getFreq () const
	{
		return freq;
	}

	int getMinorVersion() const
	{
		return glMinorVersion;
	}

	int getMadjorVersion() const
	{
		return glMadjorVersion;
	}

	bool isFullScreen() const
	{
		return isFullscreen;
	}
private:
	int		bpp;
	int		depth_bpp;
	int		width;
	int		height;
	int		freq;
	int     glMinorVersion;
    int     glMadjorVersion;
	bool	isFullscreen;
};


static  IGraphicsDevice* CreateGraphicsDevice( DeviceParameters &dp ) ;
		
        virtual ITexture*		CreateTexture(  Vector2D &size, gname::TextureCreationType, gname::TextureInternalFormat, int miplevels=0 )=0;
		
        virtual IVertexBuffer*	CreateVertexBuffer( UINT size ,int typeSize) = 0;
		virtual IIndexBuffer *	CreateIndexBuffer( )           = 0;
		virtual IShaderProgram* CreateShader(ShaderProgramType type )  = 0;
		
		  //virtual Camera &      CreateCamera() = 0;
		 // virtual void          SetCamera   () = 0;
		//  virtual Camera *	    GetCamera	() const = 0;
		virtual gname::VertexDeclaration *CreateVertexDeclaration( ) = 0;

		/* Configure render pipeline
		*/
		virtual void		SetTexture( ITexture*)=0;
		virtual void        SetShader(IShaderProgram*, bool use = true) = 0;
		virtual void		SetVertexBuffer( IVertexBuffer* )=0;
		virtual void		SetIndexBuffer( IIndexBuffer* )=0;
		
		virtual void		SetRenderTarget( ITexture* )=0;
		// Renderer info
		virtual	const char *	GetVendor		() const = 0;
	    virtual	const char *	GetRenderer		() const = 0;
	    virtual	const char *	GetVersion		() const = 0;
		
		virtual void		SetVertexDeclaration( VertexDeclaration* )=0;
		virtual void		SetSampler( Sampler* ) = 0;
		virtual void        SetClearFlags(ClearType *type) = 0;
		
		virtual void		BeginScene()                   =  0;
		virtual void		EndScene  ()                   =  0;

		virtual void		Draw(IIndexBuffer*buf)         =  0;
		virtual void		SwapBuffers()                  =  0;
		virtual void		Clear()                        =  0;
		
		
		virtual void        ClearBuffers(ClearType type)   = 0;
		// Windows managmets
        virtual	Window	*	GetWindow		() const = 0;
	    virtual	bool		SetWindow		( const string& wndName ) { return true; }
        virtual	Window	*	ECreateWindow	( const char* wndTitle, const char* wndClassName, DeviceParameters &dp) = 0;
	    virtual	void        DeleteWindow    (const string& wndName) = 0;
	
        virtual	RenderState	            *		GetRendererState	() const = 0;
	    // Renderer context managmets
		virtual	RenderContext	        *		GetRendererContext	() const = 0;
		virtual	void					        SetRendererContext	( RenderContext * context) = 0;
	 
		
		
	
	
	
	};
}
}